<?php
/**
 * ModelInstance 实例化一个数据模型
 */
namespace ulue\core\controllers\helpers;

use Ulue,
    Debug;
use ulue\base\TheAppException,
    ulue\web\Model;


final class ModelInstance
{
    static public $owner    = null;
    static public $_model   = [];#实例化过的模型对象

    /**
     * 实例化得到一个没有具体文件的表模型  Model('user')
     * 及直接实例化无参数的基础 Model()
     * 也可实例化其它  自定义基础模型:模型名  @example FromModel:User,
     * 文件 FromModel.php 请放在  ext/model/下面
     * $modelName 模型名 即是表名(有无前缀皆可)
     * @param string $modelName
     * @param string $dbConfig
     * @throws TheAppException
     */
    static public function base($modelName='', $dbConfig='')
    {
        Debug::trace("i 实例化数据模型 \$modelName $modelName",[
            '@property static $_model'=>array_keys(self::$_model)
            ]);

        $modelName          = trim($modelName);

        if (empty($modelName)) {
            return new Model();
        }

        static $_baseModel  = [];

        if ( isset($_baseModel[$modelName]) ){
            return $_baseModel[$modelName];
        }

        #实例化其它 自定义基础模型
        if ( strpos($modelName,':')!==false ){
            list($class,$modelName) = explode(':',$modelName);
            $class                  = 'ulue\exts\model\\'.$class;
            $class_file             = COMM_PATH.'/extensions/models/'. $class . Ulue::$app->get('suffix.model').'.php';

            Ulue::requireFile($class_file,'模型类文件不存在！');
        } else {
            $class = 'ulue\web\Model';
        }

        $baseModel = new $class($modelName,$dbConfig);

         Debug::trace("实例化得到了数据模型",["@internal \$class $class"],[
            '@property static $_model'=>array_keys(self::$_model)
            ]);

        if ( is_object($baseModel) ){
            $_baseModel[$modelName] = $baseModel;
        }
        else {
            throw new TheAppException('不存在模型类 ：['.$class.'] ');
        }

        return $baseModel;
    }

    /**
     * 实例化有具体模型文件的 数据模型操作类 User.php
     * @param string  $modelName 模型名 数据模型操作类名 @example user | admin\model\User
     * @param string| $dbConfig 传入数据库配置
     * @throws TheAppException
     * @return \Model
     */
    static public function get($modelName='',$dbConfig='')
    {
        Debug::trace("i 实例化数据模型 \$modelName $modelName",[
            '@property static $_model'=>array_keys(self::$_model)
            ]);

        $modelName  = trim($modelName);

        if (empty($modelName) || strpos($modelName, ':')!==false){
            return self::base($modelName, $dbConfig);
        }

        $modelLayer     = Ulue::getDir('models');
        $moduleName     = Ulue::$app->getModule()->getName();
        $class          = $modelName;

        if ( isset(self::$_model[$class]) ) {
            return self::$_model[$class];
        }

        # 带有命名空间的完整类名
        if (strpos($class, '\\') !== false) {
            // try{
                $modelName  = trim( strrchr($class,'\\') ,'\\') ;
                $existModel = new $class($modelName);
            // }catch(\Exception $e){
            //     throw new \DInstantiationException("模型类 {$realClass} 没有找到或没有实例化成功！");
            // }

            Debug::trace("实例化得到了数据模型",["@internal \$class $class"],[
                '@property static $_model'=>array_keys(self::$_model)
                ]);

            return self::$_model[$class]  =  $existModel;
        }

        # 构建当前模块下,带有命名空间的完整类名
        $realClass     = self::_getRealClass($moduleName,$modelLayer,$modelName);

        if ( $realClass )
        {
            // try{
                $existModel  =  new $realClass($modelName);
            // }catch(\Exception $e){
            //     throw new \DInstantiationException("模型类 {$realClass} 没有找到或没有实例化成功！");
            // }

            Debug::trace("实例化得到了数据模型",["@internal \$class $class"],[
                '@property static $_model'=>array_keys(self::$_model)
                ]);

            return self::$_model[$class]  =  $existModel;

        }# 实例化基础模型
        else
        {
            return self::base( strtolower($modelName) );
        }
    }

    static private function _getRealClass($moduleName,$modelLayer,$className)
    {
        $className         = ucfirst($className);
        $modelFileAtModule = Ulue::getPath('modules').'/'.$moduleName.'/'.$modelLayer.'/'.$className.'.php';
        $modleFileAtApp    = Ulue::getPath('models').'/'.$className.'.php';

        # 当前模块下的模型...
        if (file_exists($modelFileAtModule))
        {
            $namespace = $moduleName.'\\'.$modelLayer.'\\'.$className;
        }# 自动加载主应用下面的模型...
        else if (file_exists($modleFileAtApp)) {
            $namespace = Ulue::$app->defaultModule.'\\'.$modelLayer.'\\'.$className;
        }
        else {
            $namespace = false;
        }

        return $namespace;
    }

}
